#include "mystring.h"
#include <assert.h>
#include <string.h>

using namespace std;

mystring::mystring()
{
    m_str = new char[1];
    m_str[0] = '\0';
}

mystring::mystring(const char *s)
{
    size_t len = strlen(s);
    /* value initialize to zero memory */
    m_str = new char[len+1]();
    strcpy(m_str, s);
}

mystring::mystring(const mystring &str)
{
    size_t len = strlen(str.m_str);
    /* value initialize to zero memory */
    m_str = new char[len+1]();
    strcpy(m_str, str.m_str);
}

mystring &mystring::operator=(const mystring &str)
{
    mystring(str).swap(*this);
    return *this;
}

void mystring::swap(mystring &str)
{
    /* copy and swap idiom */
    std::swap(m_str, str.m_str);
}

mystring::~mystring()
{
    /* not necessary to check NULL for free() and delete */
    delete[] m_str;
}

const char *mystring::c_str() const
{
    return m_str;
}

size_t mystring::length() const
{
    return strlen(m_str);
}

char &mystring::operator[](size_t i)
{
    assert(i>=0 && i<length());
    return m_str[i];
}

const char &mystring::operator[](size_t i) const
{
    assert(i>=0 && i<length());
    return m_str[i];
}

bool mystring::operator==(const mystring &str) const
{
    return strcmp(m_str, str.m_str) == 0;
}

bool mystring::operator!=(const mystring &str) const
{
    return strcmp(m_str, str.m_str) != 0;
}

istream &operator>>(istream &stream, mystring &str)
{
    char buff[1024];
    memset(buff, 0, 1024);
    stream.getline(buff, 1024);
    mystring(buff).swap(str);
    return stream;
}

ostream &operator<<(ostream &stream, const mystring &str)
{
    stream << str.m_str;
    return stream;
}

int main()
{
    mystring s1("1234");
    mystring s2 = "1234";
    mystring s3;
    cout << "Please enter s3: ";
    cin >> s3;
    cout << "s1=" << s1 << endl;
    cout << "s2=" << s2 << endl;
    cout << "s3=" << s3 << endl;
    cout << "s1==s2? " << ((s1 == s2) ? 'Y' : 'N') << endl;
    cout << "Setting s2[1] to \'a\'.." << endl;
    s2[1] = 'a';
    cout << "s1!=s2? " << ((s1 != s2) ? 'Y' : 'N') << endl;
    return 0;
}
